package com.quiz.bis.service.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.quiz.bis.domain.model.*;
import com.quiz.bis.domain.vo.QuestionDetailVo;
import com.quiz.bis.mapper.*;
import com.quiz.bis.service.IExamAutoGradeService;
import com.quiz.bis.service.ITextSimilarityService;
import com.quiz.bis.util.text.TextPreprocessor;
import com.quiz.common.mybatis.core.query.PlusWrappers;
import com.quiz.common.utils.SecurityUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 自动评分服务实现类
 * @author ahuan
 */
@Service
@RequiredArgsConstructor
public class ExamAutoGradeServiceImpl implements IExamAutoGradeService {
    private final PaperQuestionMapper paperQuestionMapper;
    private final QuestionMapper questionMapper;
    private final ExamQuestionAnswersMapper examQuestionAnswersMapper;
    private final QuestionStatisticsMapper questionStatisticsMapper;
    private final TextPreprocessor textPreprocessor;
    private final ITextSimilarityService textSimilarityService;

    /**
     *
     * @param exam
     * @param recordId
     * @param answersJson 格式如下
     *                    {
     *
     *                    }
     * @return
     */
    @Override
    public BigDecimal start(Exam exam, Long recordId, String answersJson) {
        // 获取试卷对应的题目列表
        List<PaperQuestion> paperQuestions = paperQuestionMapper.selectList(PlusWrappers.lambdaQuery(PaperQuestion.class)
                .eq(PaperQuestion::getPaperId, exam.getPaperId()));
        Map<Long, PaperQuestion> paperQuestionMap = paperQuestions.stream()
                .collect(Collectors.toMap(PaperQuestion::getQuestionId, e -> e));
        List<Long> questionIds = paperQuestions.stream()
                .map(PaperQuestion::getQuestionId)
                .collect(Collectors.toList());

        // 考生用户id
        Long userId = SecurityUtils.getUserId();

        // 获取题目详情列表(包括答案、选项等)
        List<QuestionDetailVo> questionDetailVos = questionMapper.selectQuestionDetailListByIds(questionIds);
        Map<Long, QuestionDetailVo> questionDetailMap = questionDetailVos.stream()
                .collect(Collectors.toMap(QuestionDetailVo::getId, e -> e));

        // 解析学生答案JSON
        JSONObject answer = JSON.parseObject(answersJson);
        JSONObject answerJsonObj = JSON.parseObject(answer.getString("answers"));


        BigDecimal totalScore = BigDecimal.ZERO;
        Date now = new Date();

        // 遍历试卷中的每个题目进行批改
        List<ExamQuestionAnswers> answerRecords = new ArrayList<>();
        for (PaperQuestion pq : paperQuestions) {
            Long questionId = pq.getQuestionId();
            QuestionDetailVo questionDetail = questionDetailMap.get(questionId);
            if (questionDetail == null) {
                continue;
            }

            // 创建作答记录对象
            ExamQuestionAnswers answerRecord = new ExamQuestionAnswers();
            answerRecord.setExamId(exam.getId());
            answerRecord.setStudentRecordId(recordId);
            answerRecord.setUserId(userId);
            answerRecord.setQuestionId(questionId);
            answerRecord.setQuestionTypeId(questionDetail.getTypeId());
            answerRecord.setMaxScore(pq.getScore());
            answerRecord.setFirstAnswerTime(now);
            answerRecord.setLastUpdateTime(now);
            answerRecord.setIsSubmitted(1);

            // 获取学生答案
            Object studentAnswerObj = answerJsonObj.get(questionId.toString());

            // 根据题目类型进行不同的批改逻辑
            if (questionDetail.getHasOption() > 0) {
                // 选择题批改逻辑
                handleChoiceQuestion(answerRecord, questionDetail, studentAnswerObj, pq.getScore());
            } else if (questionDetail.getHasAnswer() == 1) {
                // 主观题批改逻辑
                handleSubjectiveQuestion(answerRecord, questionDetail, studentAnswerObj, pq.getScore());
            } else if (questionDetail.getHasAnswer() == 2) {
                // 客观题批改逻辑
                handleObjectiveQuestion(answerRecord, questionDetail, studentAnswerObj, pq.getScore());
            } else if (questionDetail.getHasAnswer() == 3) {
                // 计算题批改逻辑
                handleCalculateQuestion(answerRecord, questionDetail, studentAnswerObj, pq.getScore());
            } else if (questionDetail.getHasAnswer() == 4) {
                // 填空题批改逻辑
                handleFillQuestion(answerRecord, questionDetail, studentAnswerObj, pq.getScore());
            } else {
                // 其他类型题目不计分
                handleOtherQuestion(answerRecord, questionDetail, studentAnswerObj, pq.getScore());
            }

            // 保存作答记录
            answerRecords.add(answerRecord);

            // 更新题目统计信息
            updateQuestionStatistics(questionId, answerRecord.getIsCorrect());

            // 累加总分
            totalScore = totalScore.add(answerRecord.getScore());
        }
        examQuestionAnswersMapper.insertBatch(answerRecords);

        return totalScore;
    }




    /**
     * 处理选择题批改
     */
    private void handleChoiceQuestion(ExamQuestionAnswers answerRecord, QuestionDetailVo questionDetail,
                                      Object studentAnswerObj, BigDecimal maxScore) {
        // 获取正确答案选项
        Map<Long, QuestionOption> correctOptionMap = questionDetail.getOptions().stream()
                .collect(Collectors.toList()).stream().collect(Collectors.toMap(QuestionOption::getId, e -> e));
        // 解析学生答案
        List<String> studentSelectedCodes = new ArrayList<>();
        List<Long> studentSelectedIds = new ArrayList<>();
        if (studentAnswerObj instanceof Long|| studentAnswerObj instanceof Integer) {
            // 单选题
            studentSelectedIds.add(Long.valueOf((Integer) studentAnswerObj));
        } else if (studentAnswerObj instanceof JSONArray) {
            // 多选题
            studentSelectedIds = ((JSONArray) studentAnswerObj).toJavaList(Long.class);
        }


        // 判断是否正确
        boolean isCorrect = false;
        if (questionDetail.getHasOption() == 1) {
            // 单选题 - 必须完全匹配
            QuestionOption questionOption = correctOptionMap.get(studentSelectedIds.get(0));
            if(questionOption != null){
                isCorrect = questionOption.getIsCorrect() == 1;
                studentSelectedCodes.add(questionOption.getOptionCode());
            }
        } else {
            // 多选题 - 必须完全匹配所有选项
            for (Long id : studentSelectedIds) {
                QuestionOption questionOption = correctOptionMap.get(id);
                if (questionOption != null) {
                    isCorrect = questionOption.getIsCorrect() == 1;
                    studentSelectedCodes.add(questionOption.getOptionCode());
                }
            }
        }

        // 记录学生选择的选项编码
        answerRecord.setSelectedOptionIds(JSON.toJSONString(studentSelectedIds));
        answerRecord.setSelectedOptionCodes(JSON.toJSONString(studentSelectedCodes));


        // 设置批改结果
        answerRecord.setIsCorrect(isCorrect ? 1 : 0);
        answerRecord.setScore(isCorrect ? maxScore : BigDecimal.ZERO);
        answerRecord.setAutoScore(isCorrect ? maxScore : BigDecimal.ZERO);
        answerRecord.setScoreStatus(1); // 自动评分完成
    }



    /**
     * 处理主观题批改 - 精确匹配
     */
    private void handleSubjectiveQuestion(ExamQuestionAnswers answerRecord, QuestionDetailVo questionDetail,
                                          Object studentAnswerObj, BigDecimal maxScore) {
        if (!(studentAnswerObj instanceof String)) {
            answerRecord.setIsCorrect(0);
            answerRecord.setScore(BigDecimal.ZERO);
            answerRecord.setAutoScore(BigDecimal.ZERO);
            answerRecord.setScoreStatus(0); // 未评分
            return;
        }

        String studentAnswer = (String) studentAnswerObj;
        answerRecord.setAnswerContent(studentAnswer);

        // 获取标准答案
        List<QuestionAnswer> answers = questionDetail.getAnswers();
        if (answers == null || answers.isEmpty()) {
            answerRecord.setIsCorrect(0);
            answerRecord.setScore(BigDecimal.ZERO);
            answerRecord.setAutoScore(BigDecimal.ZERO);
            answerRecord.setScoreStatus(0); // 未评分
            return;
        }

        // 使用文本相似度进行精确匹配
        String standardAnswer = answers.get(0).getContentText();
//        double similarity = calculateTextSimilarity(studentAnswer, standardAnswer);
        double similarity = textSimilarityService.calculateSimilarity(studentAnswer, standardAnswer);

        // 设置批改结果
        if (similarity > 0.8) { // 相似度大于80%认为正确
            answerRecord.setIsCorrect(1);
            answerRecord.setScore(maxScore);
            answerRecord.setAutoScore(maxScore);
        } else {
            answerRecord.setIsCorrect(0);
            answerRecord.setScore(BigDecimal.ZERO);
            answerRecord.setAutoScore((maxScore.multiply(BigDecimal.valueOf(similarity))));
        }
        answerRecord.setScoreStatus(1); // 自动评分完成
    }

    /**
     * 处理客观题批改 - 关键词匹配
     */
    private void handleObjectiveQuestion(ExamQuestionAnswers answerRecord, QuestionDetailVo questionDetail,
                                         Object studentAnswerObj, BigDecimal maxScore) {
        if (!(studentAnswerObj instanceof String)) {
            answerRecord.setIsCorrect(0);
            answerRecord.setScore(BigDecimal.ZERO);
            answerRecord.setAutoScore(BigDecimal.ZERO);
            answerRecord.setScoreStatus(0); // 未评分
            return;
        }

        String studentAnswer = (String) studentAnswerObj;
        answerRecord.setAnswerContent(studentAnswer);

        // 获取标准答案
        List<QuestionAnswer> answers = questionDetail.getAnswers();
        if (answers == null || answers.isEmpty()) {
            answerRecord.setIsCorrect(0);
            answerRecord.setScore(BigDecimal.ZERO);
            answerRecord.setAutoScore(BigDecimal.ZERO);
            answerRecord.setScoreStatus(0); // 未评分
            return;
        }

        // 使用关键词匹配
        String standardAnswer = answers.get(0).getContentText();
        ProcessedText studentPreprocess = textPreprocessor.preprocess(studentAnswer);
        ProcessedText standardPreprocess = textPreprocessor.preprocess(standardAnswer);
//        double matchScore = calculateKeywordMatchScore(studentAnswer, standardAnswer);
        double matchScore = calculateKeywordMatchScore(studentPreprocess.getCleanText(), standardPreprocess.getWords());

        // 设置批改结果
        if (matchScore > 0.7) { // 匹配度大于70%认为正确
            answerRecord.setIsCorrect(1);
            answerRecord.setScore(maxScore);
            answerRecord.setAutoScore(maxScore);
        } else if (matchScore > 0.3) { // 匹配度30%-70%部分正确
            answerRecord.setIsCorrect(2);
            answerRecord.setScore(maxScore.multiply(BigDecimal.valueOf(0.5)));
            answerRecord.setAutoScore(maxScore.multiply(BigDecimal.valueOf(0.5)));
        } else {
            answerRecord.setIsCorrect(0);
            answerRecord.setScore(BigDecimal.ZERO);
            answerRecord.setAutoScore(BigDecimal.ZERO);
        }
        answerRecord.setScoreStatus(1); // 自动评分完成
    }


    private void handleCalculateQuestion(ExamQuestionAnswers answerRecord, QuestionDetailVo questionDetail, Object studentAnswerObj, BigDecimal maxScore) {
        if (!(studentAnswerObj instanceof String)) {
            answerRecord.setIsCorrect(0);
            answerRecord.setScore(BigDecimal.ZERO);
            answerRecord.setAutoScore(BigDecimal.ZERO);
            answerRecord.setScoreStatus(0); // 未评分
            return;
        }

        String studentAnswer = (String) studentAnswerObj;
        answerRecord.setAnswerContent(studentAnswer);

        // 获取标准答案
        List<QuestionAnswer> answers = questionDetail.getAnswers();
        if (answers == null || answers.isEmpty()) {
            answerRecord.setIsCorrect(0);
            answerRecord.setScore(BigDecimal.ZERO);
            answerRecord.setAutoScore(BigDecimal.ZERO);
            answerRecord.setScoreStatus(0); // 未评分
            return;
        }

        // 使用XXXXXXX匹配
        String standardAnswer = answers.get(0).getContentText();
//        double matchScore = calculateKeywordMatchScore(studentAnswer, standardAnswer);

        // 设置批改结果（暂时设置默认值）
        answerRecord.setIsCorrect(0);
        answerRecord.setScore(maxScore);
        answerRecord.setAutoScore(BigDecimal.ZERO);
        answerRecord.setScoreStatus(1); // 自动评分完成
    }

    private void handleFillQuestion(ExamQuestionAnswers answerRecord, QuestionDetailVo questionDetail, Object studentAnswerObj, BigDecimal maxScore) {
        if (!(studentAnswerObj instanceof String)) {
            answerRecord.setIsCorrect(0);
            answerRecord.setScore(BigDecimal.ZERO);
            answerRecord.setAutoScore(BigDecimal.ZERO);
            answerRecord.setScoreStatus(0); // 未评分
            return;
        }

        String studentAnswer = (String) studentAnswerObj;
        answerRecord.setAnswerContent(studentAnswer);

        // 获取标准答案
        List<QuestionAnswer> answers = questionDetail.getAnswers();
        if (answers == null || answers.isEmpty()) {
            answerRecord.setIsCorrect(0);
            answerRecord.setScore(BigDecimal.ZERO);
            answerRecord.setAutoScore(BigDecimal.ZERO);
            answerRecord.setScoreStatus(0); // 未评分
            return;
        }

        // 使用人工批改
        String standardAnswer = answers.get(0).getContentText();
//        double matchScore = calculateKeywordMatchScore(studentAnswer, standardAnswer);

        // 设置批改结果（暂时设置默认值）
        answerRecord.setIsCorrect(0);
        answerRecord.setScore(maxScore);
        answerRecord.setAutoScore(BigDecimal.ZERO);
        answerRecord.setScoreStatus(1); // 自动评分完成
    }

    private void handleOtherQuestion(ExamQuestionAnswers answerRecord, QuestionDetailVo questionDetail, Object studentAnswerObj, BigDecimal score) {
        String studentAnswer = (String) studentAnswerObj;
        // 获取标准答案
        answerRecord.setAnswerContent(studentAnswer);
        answerRecord.setIsCorrect(0);
        answerRecord.setScore(BigDecimal.ZERO);
        answerRecord.setAutoScore(BigDecimal.ZERO);
        answerRecord.setScoreStatus(0); // 未评分
    }

    /**
     * 计算文本相似度
     */
    private double calculateTextSimilarity(String text1, String text2) {
        // 简单实现 - 实际可以使用更复杂的算法如余弦相似度等
        if (text1 == null || text2 == null) {
            return 0;
        }

        // 去除空白字符
        String s1 = text1.replaceAll("\\s+", "");
        String s2 = text2.replaceAll("\\s+", "");

        if (s1.isEmpty() || s2.isEmpty()) {
            return 0;
        }

        // 使用编辑距离计算相似度
        int maxLength = Math.max(s1.length(), s2.length());
        if (maxLength == 0) {
            return 1.0;
        }

        double distance = (double) calculateLevenshteinDistance(s1, s2);
        return 1.0 - (distance / maxLength);
    }

    /**
     * 计算编辑距离
     */
    private int calculateLevenshteinDistance(String s, String t) {
        int m = s.length();
        int n = t.length();
        int[][] dp = new int[m + 1][n + 1];

        for (int i = 0; i <= m; i++) {
            dp[i][0] = i;
        }

        for (int j = 0; j <= n; j++) {
            dp[0][j] = j;
        }

        for (int i = 1; i <= m; i++) {
            for (int j = 1; j <= n; j++) {
                if (s.charAt(i - 1) == t.charAt(j - 1)) {
                    dp[i][j] = dp[i - 1][j - 1];
                } else {
                    dp[i][j] = 1 + Math.min(dp[i - 1][j - 1],
                            Math.min(dp[i][j - 1], dp[i - 1][j]));
                }
            }
        }

        return dp[m][n];
    }

    /**
     * 计算关键词匹配得分
     */
    private double calculateKeywordMatchScore(String text, List<String> keywords) {
        // 简单实现 - 实际可以使用分词工具和TF-IDF等算法
        if (text == null || keywords == null || keywords.isEmpty()) {
            return 0;
        }

        // 将关键词按逗号或空格分割
//        String[] keywordArray = keywords.split("[,\\s]+");
//        if (keywordArray.length == 0) {
//            return 0;
//        }

        int matchedCount = 0;
        for (String keyword : keywords) {
            if (text.contains(keyword)) {
                matchedCount++;
            }
        }

        return (double) matchedCount / keywords.size();
    }

    /**
     * 更新题目统计信息
     */
    private void updateQuestionStatistics(Long questionId, Integer isCorrect) {
        // 查询现有统计信息
        QuestionStatistics statistics = questionStatisticsMapper.selectOne(
                PlusWrappers.lambdaQuery(QuestionStatistics.class)
                        .eq(QuestionStatistics::getQuestionId, questionId));

        if (statistics == null) {
            // 如果没有统计记录，创建一条新的
            statistics = new QuestionStatistics();
            statistics.setQuestionId(questionId);
            statistics.setViewCount(0);
            statistics.setUseCount(1);
            statistics.setPaperCount(0);
            statistics.setCorrectCount(isCorrect == 1 ? 1 : 0);
            statistics.setWrongCount(isCorrect == 0 ? 1 : 0);
            questionStatisticsMapper.insert(statistics);
        } else {
            // 更新现有统计信息
            statistics.setUseCount(statistics.getUseCount() + 1);
            if (isCorrect == 1) {
                statistics.setCorrectCount(statistics.getCorrectCount() + 1);
            } else {
                statistics.setWrongCount(statistics.getWrongCount() + 1);
            }
            questionStatisticsMapper.updateById(statistics);
        }
    }

}
